
#include <BFile>
#include "member_BObcDocument.h"

using namespace BWE;

#define RegistObjectSign(type, sign) regist(B##type::TypeName(), sign, (readFunc)&member_BObcDocument::read##type, (writeFunc)&member_BObcDocument::write##type)

member_BObcDocument::member_BObcDocument(BObcDocument* obcDocument)
{
	boss = obcDocument;
	if (signTypeMap.empty())
	{
		RegistObjectSign(Object, SIGN_OBJECT);
		RegistObjectSign(Scene, SIGN_SCENE);
		RegistObjectSign(Node, SIGN_NODE);
		RegistObjectSign(Light, SIGN_LIGHT);
		RegistObjectSign(Camera, SIGN_CAMERA);
		RegistObjectSign(Group, SIGN_GROUP);

		RegistObjectSign(Shape, SIGN_SHAPE);
		RegistObjectSign(Mesh, SIGN_MESH);
		RegistObjectSign(Geometry, SIGN_GEOMETRY);
		RegistObjectSign(Textual, SIGN_TEXTUAL);
		RegistObjectSign(Particle, SIGN_PARTICLE);
		RegistObjectSign(Element, SIGN_ELEMENT);

		RegistObjectSign(Cube, SIGN_CUBE);
		RegistObjectSign(Cone, SIGN_CONE);
		RegistObjectSign(Cylinder, SIGN_CYLINDER);
		RegistObjectSign(Sphere, SIGN_SPHERE);
		RegistObjectSign(GeoSphere, SIGN_GEOSPHERE);
		RegistObjectSign(Tube, SIGN_TUBE);
		RegistObjectSign(Torus, SIGN_TORUS);
		RegistObjectSign(Surface, SIGN_SURFACE);
		RegistObjectSign(Terrain, SIGN_TERRAIN);
		RegistObjectSign(Billboard, SIGN_BILLBOARD);
		RegistObjectSign(Particle, SIGN_PARTICLE);
		RegistObjectSign(Capsule, SIGN_CAPSULE);

		RegistObjectSign(Constraint, SIGN_CONSTRAINT);
		RegistObjectSign(PointConstraint, SIGN_POINT_CONSTRAINT);
		RegistObjectSign(HingeConstraint, SIGN_HINGE_CONSTRAINT);
		RegistObjectSign(SliderConstraint, SIGN_SLIDER_CONSTRAINT);
		RegistObjectSign(ConearConstraint, SIGN_CONEAR_CONSTRAINT);
		RegistObjectSign(SixdofConstraint, SIGN_SIXDOF_CONSTRAINT);

		RegistObjectSign(Material, SIGN_MATERIAL);
		RegistObjectSign(Texture, SIGN_TEXTURE);
		RegistObjectSign(Image, SIGN_IMAGE);
		RegistObjectSign(Pixmap, SIGN_PIXMAP);
		RegistObjectSign(Program, SIGN_PROGRAM);
		RegistObjectSign(Uniform, SIGN_UNIFORM);
		RegistObjectSign(Physics, SIGN_PHYSICS);
		RegistObjectSign(Script, SIGN_SCRIPT);
		RegistObjectSign(Source, SIGN_SOURCE);

	}
}
member_BObcDocument::~member_BObcDocument()
{

}

void member_BObcDocument::reset()
{
	stream = 0;
	chunkLevel = 0;
	chunkStack.clear();
	readObjectMap.clear();
	writeObjectMap.clear();
}

bool member_BObcDocument::readBeginChunk(Chunk& chunk, int end)
{
	if (stream->offset() >= end)
		return false;
	if (!stream->read(&chunk, 6))
		return false;
	//static BString text;
	//text.reset();
	//text.append('\t', chunkLevel);
	//text << ChunkNames[chunk.sign] << " : " << chunk.size;
	//puts(text.cstr());
	chunkLevel++;
	return true;
}
bool member_BObcDocument::readEndChunk(Chunk& chunk)
{
	chunkLevel--;
	if (!stream->seek(chunk.end))
	{
		static BString text;
		text.reset();
		text.append('\t', chunkLevel);
		text << signTypeMap(chunk.sign) << "end faild";
		//puts(text.cstr());
		return false;
	}
	return true;
}

BObject* member_BObcDocument::read(const Chunk& chunk)
{
	int id = 0;
	Chunk head;
	if (readBeginChunk(head, chunk.end))
	{
		if (head.sign == SIGN_ID)
			stream->read(id);
		else
			stream->move(-6);
	}
	if (id > 0)
	{
		BObject* object = readObjectMap(id);
		if (object)
			return object;
	}

	BObject* object = boss->create(chunk.sign);
	if (!object)
	{
		message() << "OBC Error : Create object failed : " << signTypeMap(chunk.sign);
		return 0;
	}

	BArray<member_BObcDocument::readFunc> readFuncs;
	BArray<BObcDocument::readChunk> readChunks;
	for (int i = 0; i < object->typeCount(); i++)
	{
		const char* type = object->typeName(i);
		if (member_BObcDocument::readFunc read = readFuncMap(type))
		{
			readFuncs.append(read);
			continue;
		}
		if (BObcDocument::readChunk read = readChunkMap(type))
			readChunks.append(read);
	}

	Chunk sub;
	while (readBeginChunk(sub, chunk.end))
	{
		bool result = false;
		for (int i = 0; i < readFuncs.size(); i++)
		{
			member_BObcDocument::readFunc read = readFuncs[i];
			if ((this->*read)(sub, object))
			{
				result = true;
				break;
			}
		}
		if (!result && readChunks.size())
		{
			for (int i = 0; i < readChunks.size(); i++)
			{
				BObcDocument::readChunk read = readChunks[i];
				if ((boss->*read)(stream, sub.sign, object))
				{
					result = true;
					break;
				}
			}
		}
		if (!result)
		{
			message() << "OBC Error : [" << signTypeMap(chunk.sign) << "] invalid sub chunk " << signTypeMap(sub.sign) << '[' << sub.sign << "]\n";
		}
	}
	if (id > 0)
	{
		readObjectMap[id] = object;
	}
	return object;
}
bool member_BObcDocument::write(const BObject* object)
{
	BUShort sign = SIGN_NONE;
	BArray<member_BObcDocument::writeFunc> writeFuncs;
	BArray<BObcDocument::writeChunk> writeChunks;
	for (int i = 0; i < object->typeCount(); i++)
	{
		const char* typeName = object->typeName(i);
		if (member_BObcDocument::writeFunc write = writeFuncMap(typeName))
		{
			writeFuncs.append(write);
			sign = typeSignMap(typeName);
			continue;
		}
		if (BObcDocument::writeChunk write = writeChunkMap(typeName))
		{
			writeChunks.append(write);
			sign = typeSignMap(typeName);
			continue;
		}
	}
	if (writeFuncs.empty())
	{
		message() << "OBC Error : Write object failed : No read func for " << object->className();
		return false;
	}
	int id = writeObjectMap(object);
	if (id == 0 && object->ref_count() > 1)
	{
		id = writeObjectMap.size() + 1;
		writeObjectMap.insert(object, id);
	}
	AutoChunk chunk(this, sign);
	if (id > 0)
	{
		AutoChunk idchunk(this, SIGN_ID);
		stream->write(id);
	}
	for (int i = 0; i < writeFuncs.size(); i++)
	{
		member_BObcDocument::writeFunc write = writeFuncs[i];
		if (!(this->*write)(object))
		{
			message() << "OBC Error : Write object failed " << object->className();
			return false;
		}
	}
	for (int i = 0; i < writeChunks.size(); i++)
	{
		BObcDocument::writeChunk write = writeChunks[i];
		if (!(boss->*write)(stream, object))
		{
			message() << "OBC Error : Write object failed " << object->className();
			return false;
		}
	}
	return true;
}

bool member_BObcDocument::readObject(const Chunk& chunk, BObject* object)
{
	switch (chunk.sign)
	{
	case SIGN_NAME:
	{
		BString name;
		stream->read(name);
		object->setName(name);
		break;
	}
	case SIGN_ENABLED:
	{
		bool enabled = false;
		stream->read(enabled);
		object->setEnabled(enabled);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readNode(const Chunk& chunk, BNode* node)
{
	switch (chunk.sign)
	{
	case SIGN_VISIBLE:
	{
		bool visible = true;
		stream->read(visible);
		node->setVisible(visible);
		break;
	}
	case SIGN_OPTIMIZED:
	{
		bool optimized = false;
		stream->read(optimized);
		node->setOptimized(optimized);
		break;
	}
	case SIGN_MATRIX:
	{
		BMatrixf matrix;
		stream->read(matrix);
		node->setMatrix(matrix);
		break;
	}
	case SIGN_MATRIX_D:
	{
		BMatrixd matrix;
		stream->read(matrix);
		node->setMatrix(matrix);
		break;
	}
	default:
		BHolder<BObject> object = read(chunk);
		if (BShape* shape = object.as<BShape>())
		{
			node->addShape(shape);
			break;
		}
		if (BPhysics* physics = object.as<BPhysics>())
		{
			node->setPhysics(physics);
			break;
		}
		return false;
	}
	return true;
}
bool member_BObcDocument::readScene(const Chunk& chunk, BScene* scene)
{
	switch (chunk.sign)
	{
	case SIGN_OPTIMIZED:
	{
		bool optimized = false;
		stream->read(optimized);
		break;
	}
	default:
	{
		BObjectHolder object = read(chunk);
		if (BShape* shape = object.as<BShape>())
			scene->insert(shape);
		else if (BNode* node = object.as<BNode>())
			scene->insert(node);
		else if (BConstraint* constraint = object.as<BConstraint>())
			scene->insert(constraint);
		else if (BGroup* group = object.as<BGroup>())
			scene->insert(group);
		else
			return false;
	}
	}
	return true;
}
bool member_BObcDocument::readGroup(const Chunk& chunk, BGroup* group)
{
	BObjectHolder object = read(chunk);
	if (BShape* shape = object.as<BShape>())
		group->insert(shape);
	else if (BNode* node = object.as<BNode>())
		group->insert(node);
	else if (BGroup* childGroup = object.as<BGroup>())
		group->addChild(childGroup);
	else if (BConstraint* constraint = object.as<BConstraint>())
		group->insert(constraint);
	else
		return false;
	return true;
}
bool member_BObcDocument::readLight(const Chunk& chunk, BLight* light)
{
	switch (chunk.sign)
	{
	case SIGN_TYPE:
	{
		BLight::Type type = BLight::Type_Point;
		stream->read(type);
		light->setType(type);
		break;
	}
	case SIGN_AMBIENT:
	{
		BColor ambient;
		stream->read(ambient);
		light->setAmbient(ambient);
		break;
	}
	case SIGN_DIFFUSE:
	{
		BColor diffuse;
		stream->read(diffuse);
		light->setDiffuse(diffuse);
		break;
	}
	case SIGN_SPECULAR:
	{
		BColor specular;
		stream->read(specular);
		light->setSpecular(specular);
		break;
	}
	case SIGN_ATTENUATION:
	{
		float attenuation = 0.0f;
		stream->read(attenuation);
		light->setAttenuation(attenuation);
		break;
	}
	case SIGN_ATTENUATION2:
	{
		float attenuation2 = 0.0f;
		stream->read(attenuation2);
		light->setAttenuation2(attenuation2);
		break;
	}
	case SIGN_CUTOFF:
	{
		float cutoff = 0.0f;
		stream->read(cutoff);
		light->setCutoff(cutoff);
		break;
	}
	case SIGN_EXPONENT:
	{
		float exponent = 0.0f;
		stream->read(exponent);
		light->setExponent(exponent);
		break;
	}
	case SIGN_DIRECTION:
	{
		BVectorf direction;
		light->setDirection(direction);
		break;
	}
	case SIGN_DIRECTION_D:
	{
		BVectord direction;
		light->setDirection(direction);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readCamera(const Chunk& chunk, BCamera* camera)
{
	switch (chunk.sign)
	{
	case SIGN_ORTHO:
	{
		bool ortho;
		stream->read(ortho);
		camera->setOrtho(ortho);
		break;
	}
	case SIGN_CENTER:
	{
		BVectorf center;
		stream->read(center);
		camera->setCenter(center);
		break;
	}
	case SIGN_CENTER_D:
	{
		BVectord center;
		stream->read(center);
		camera->setCenter(center);
		break;
	}
	case SIGN_UP:
	{
		BVectorf up;
		stream->read(up);
		camera->setUp(up);
		break;
	}
	case SIGN_UP_D:
	{
		BVectord up;
		stream->read(up);
		camera->setUp(up);
		break;
	}
	case SIGN_NEAR:
	{
		float near;
		stream->read(near);
		break;
	}
	case SIGN_NEAR_D:
	{
		double near;
		stream->read(near);
		break;
	}
	case SIGN_FAR:
	{
		float far;
		stream->read(far);
		camera->setFar(far);
		break;
	}
	case SIGN_FAR_D:
	{
		double far;
		stream->read(far);
		camera->setFar(far);
		break;
	}
	case SIGN_FOVY:
	{
		float fovy;
		stream->read(fovy);
		camera->setFovy(fovy);
		break;
	}
	case SIGN_FOVY_D:
	{
		double fovy;
		stream->read(fovy);
		camera->setFovy(fovy);
		break;
	}
	case SIGN_ASPECT:
	{
		float aspect;
		stream->read(aspect);
		camera->setAspect(aspect);
		break;
	}
	case SIGN_ASPECT_D:
	{
		double aspect;
		stream->read(aspect);
		camera->setAspect(aspect);
		break;
	}
	case SIGN_LENSSIZE:
	{
		float lensWidth, lensHeight;
		stream->read(lensWidth);
		stream->read(lensHeight);
		camera->setLensWidth(lensWidth);
		camera->setLensHeight(lensHeight);
		break;
	}
	case SIGN_LENSSIZE_D:
	{
		double lensWidth, lensHeight;
		stream->read(lensWidth);
		stream->read(lensHeight);
		camera->setLensWidth(lensWidth);
		camera->setLensHeight(lensHeight);
		break;
	}
	case SIGN_PIXELSIZE:
	{
		int pixelWidth, pixelHeight;
		stream->read(pixelWidth);
		stream->read(pixelHeight);
		camera->setPixelSize(pixelWidth, pixelHeight);
		break;
	}
	case SIGN_PIXELPOLICY:
	{
		Policy pixelPolicy;
		stream->read(pixelPolicy);
		camera->setPixelSizePolicy(pixelPolicy);
		break;
	}
	case SIGN_BACKGROUND:
	{
		BColor color;
		stream->read(color);
		camera->setColor(color);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readBillboard(const Chunk& chunk, BBillboard* billboard)
{
	switch (chunk.sign)
	{
	case SIGN_AXIS:
	{
		BVectorf axis;
		stream->read(axis);
		billboard->setAxis(axis);
		break;
	}
	case SIGN_AXIS_D:
	{
		BVectord axis;
		stream->read(axis);
		billboard->setAxis(axis);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readConstraint(const Chunk& chunk, BConstraint* constraint)
{
	switch (chunk.sign)
	{
	case SIGN_NODEA:
	{
		int idA = 0;
		stream->read(idA);
		BNode* nodeA = dynamic_cast<BNode*>(readObjectMap[idA]);
		constraint->setNodeA(nodeA);
		break;
	}
	case SIGN_POINTA:
	{
		BVectorf pointA;
		stream->read(pointA);
		constraint->setPointA(pointA);
		break;
	}
	case SIGN_POINTA_D:
	{
		BVectord pointA;
		stream->read(pointA);
		constraint->setPointA(pointA);
		break;
	}
	case SIGN_NODEB:
	{
		int idB = 0;
		stream->read(idB);
		BNode* nodeB = dynamic_cast<BNode*>(readObjectMap[idB]);
		constraint->setNodeB(nodeB);
		break;
	}
	case SIGN_POINTB:
	{
		BVector pointB;
		stream->read(pointB);
		constraint->setPointB(pointB);
		break;
	}
	case SIGN_POINTB_D:
	{
		BVectord pointB;
		stream->read(pointB);
		constraint->setPointB(pointB);
		break;
	}
	case SIGN_INNER_COLLIBLE:
	{
		bool innerCollible = false;
		stream->read(innerCollible);
		constraint->setInnerCollible(innerCollible);
		break;
	}
	case SIGN_BREAK_IMPULSE:
	{
		float breakImpulse = 0;
		stream->read(breakImpulse);
		constraint->setBreakImpulse(breakImpulse);
		break;
	}
	case SIGN_BREAK_IMPULSE_D:
	{
		double breakImpulse = 0;
		stream->read(breakImpulse);
		constraint->setBreakImpulse(breakImpulse);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readPointConstraint(const Chunk& chunk, BPointConstraint* constraint)
{
	return false;
}
bool member_BObcDocument::readHingeConstraint(const Chunk& chunk, BHingeConstraint* constraint)
{
	return false;
}
bool member_BObcDocument::readSliderConstraint(const Chunk& chunk, BSliderConstraint* constraint)
{
	switch (chunk.sign)
	{
	case SIGN_AXISA:
	{
		BVectorf axisA;
		stream->read(axisA);
		constraint->setAxisA(axisA);
		break;
	}
	case SIGN_AXISA_D:
	{
		BVectord axisA;
		stream->read(axisA);
		constraint->setAxisA(axisA);
		break;
	}
	case SIGN_AXISB:
	{
		BVectorf axisB;
		stream->read(axisB);
		constraint->setAxisB(axisB);
		break;
	}
	case SIGN_AXISB_D:
	{
		BVectord axisB;
		stream->read(axisB);
		constraint->setAxisB(axisB);
		break;
	}
	case SIGN_LINEAR_LIMIT:
	{
		BRangef linearLimit;
		stream->read(linearLimit);
		constraint->setLinearLimit(linearLimit);
		break;
	}
	case SIGN_LINEAR_LIMIT_D:
	{
		BRanged linearLimit;
		stream->read(linearLimit);
		constraint->setLinearLimit(linearLimit);
		break;
	}
	case SIGN_ANGLE_LIMIT:
	{
		BRangef angleLimit;
		stream->read(angleLimit);
		constraint->setAngleLimit(angleLimit);
		break;
	}
	case SIGN_ANGLE_LIMIT_D:
	{
		BRanged angleLimit;
		stream->read(angleLimit);
		constraint->setAngleLimit(angleLimit);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readConearConstraint(const Chunk& chunk, BConearConstraint* constraint)
{
	return false;
}
bool member_BObcDocument::readSixdofConstraint(const Chunk& chunk, BSixdofConstraint* constraint)
{
	return false;
}

bool member_BObcDocument::readShape(const Chunk& chunk, BShape* shape)
{
	switch (chunk.sign)
	{
	case SIGN_VISIBLE:
	{
		bool visible = true;
		stream->read(visible);
		shape->setVisible(visible);
		break;
	}
	case SIGN_LIGHTING:
	{
		bool lighting = false;
		stream->read(lighting);
		shape->setLighting(lighting);
		break;
	}
	case SIGN_CULLBACK:
	{
		bool cullback = false;
		stream->read(cullback);
		shape->setCullback(cullback);
		break;
	}
	case SIGN_DEPTHTEST:
	{
		bool depthTest = false;
		stream->read(depthTest);
		shape->setDepthTest(depthTest);
		break;
	}
	case SIGN_TRANSPARENT:
	{
		bool transparent = false;
		stream->read(transparent);
		shape->setTransparent(transparent);
		break;
	}
	case SIGN_POINTSMOOTH:
	{
		bool pointSmooth = false;
		stream->read(pointSmooth);
		shape->setPointSmooth(pointSmooth);
		break;
	}
	case SIGN_POINTSIZE:
	{
		int pointSize = 1;
		stream->read(pointSize);
		shape->setPointSize(pointSize);
		break;
	}
	case SIGN_LINESMOOTH:
	{
		bool lineSmooth = false;
		stream->read(lineSmooth);
		shape->setLineSmooth(lineSmooth);
		break;
	}
	case SIGN_LINEWIDTH:
	{
		int lineWidth = 1;
		stream->read(lineWidth);
		shape->setLineWidth(lineWidth);
		break;
	}
	case SIGN_POLYGONSMOOTH:
	{
		bool polygonSmooth = false;
		stream->read(polygonSmooth);
		shape->setPolygonSmooth(polygonSmooth);
		break;
	}
	case SIGN_POLYGONMODE:
	{
		char polyMode = Poly_Fill;
		stream->read(polyMode);
		shape->setPolyMode((PolyMode)polyMode);
		break;
	}
	case SIGN_MATRIX:
	{
		BMatrixf matrix;
		stream->read(matrix);
		shape->setMatrix(matrix);
		break;
	}
	case SIGN_MATRIX_D:
	{
		BMatrixd matrix;
		stream->read(matrix);
		shape->setMatrix(matrix);
		break;
	}
	case SIGN_COLOR:
	{
		BColor color;
		stream->read(color);
		shape->setColor(color);
		break;
	}
	case SIGN_MATERIAL:
	{
		BMaterial* material = (BMaterial*)read(chunk);
		shape->setMaterial(material);
		break;
	}
	case SIGN_IMAGE:
	{
		BTexture* texture = (BTexture*)read(chunk);
		shape->setTexture(texture);
		break;
	}
	case SIGN_PIXMAP:
	{
		BTexture* texture = (BTexture*)read(chunk);
		shape->setTexture(texture);
		break;
	}
	case SIGN_PROGRAM:
	{
		BProgram* program = (BProgram*)read(chunk);
		shape->setProgram(program);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readMesh(const Chunk& chunk, BMesh* mesh)
{
	switch (chunk.sign)
	{
	case SIGN_OPTIMIZED:
	{
		bool optimized = false;
		stream->read(optimized);
		mesh->setOptimized(optimized);
		break;
	}
	case SIGN_VERTICES:
	{
		int size = 0;
		stream->read(size);
		BVectorfArray vertices(size);
		stream->read(vertices.data(), size * sizeof(BVectorf));
		mesh->setVertices(new BVectorArray(vertices));
		break;
	}
	case SIGN_VERTICES_D:
	{
		int size = 0;
		stream->read(size);
		BVectordArray vertices(size);
		stream->read(vertices.data(), size * sizeof(BVectord));
		mesh->setVertices(new BVectorArray(vertices));
		break;
	}
	case SIGN_NORMALS:
	{
		int size = 0;
		stream->read(size);
		BVectorfArray normals(size);
		stream->read(normals.data(), size * sizeof(BVectorf));
		mesh->setNormals(new BVectorArray(normals));
		break;
	}
	case SIGN_NORMALS_D:
	{
		int size = 0;
		stream->read(size);
		BVectordArray normals(size);
		stream->read(normals.data(), size * sizeof(BVectord));
		mesh->setNormals(new BVectorArray(normals));
		break;
	}
	case SIGN_TEXCOORDS:
	{
		int size = 0;
		stream->read(size);
		BCoordArray* texCoords = new BCoordArray(size);
		stream->read(texCoords->data(), size * sizeof(BCoord));
		mesh->setTexCoords(texCoords);
		break;
	}
	case SIGN_FACES:
	{
		int size = 0;
		stream->read(size);
		BFaceArray* faces = new BFaceArray(size);
		stream->read(faces->data(), size * sizeof(BFace));
		mesh->setFaces(faces);
		break;
	}
	case SIGN_COLORS:
	{
		int size = 0;
		stream->read(size);
		BColorArray* colors = new BColorArray(size);
		stream->read(colors->data(), size * sizeof(BColor));
		mesh->setColors(colors);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readGeometry(const Chunk& chunk, BGeometry* geometry)
{
	switch (chunk.sign)
	{
	case SIGN_OPTIMIZED:
	{
		bool optimized = false;
		stream->read(optimized);
		geometry->setOptimized(optimized);
		break;
	}
	case SIGN_VERTICES:
	{
		int size = 0;
		stream->read(size);
		BVectorfArray vertices(size);
		stream->read(vertices.data(), size * sizeof(BVectorf));
		geometry->setVertices(new BVectorArray(vertices));
		break;
	}
	case SIGN_VERTICES_D:
	{
		int size = 0;
		stream->read(size);
		BVectordArray vertices(size);
		stream->read(vertices.data(), size * sizeof(BVectord));
		geometry->setVertices(new BVectorArray(vertices));
		break;
	}
	case SIGN_NORMALS:
	{
		int size = 0;
		stream->read(size);
		BVectorfArray normals(size);
		stream->read(normals.data(), size * sizeof(BVectorf));
		geometry->setNormals(new BVectorArray(normals));
		break;
	}
	case SIGN_NORMALS_D:
	{
		int size = 0;
		stream->read(size);
		BVectordArray normals(size);
		stream->read(normals.data(), size * sizeof(BVectord));
		geometry->setNormals(new BVectorArray(normals));
		break;
	}
	case SIGN_TEXCOORDS:
	{
		int size = 0;
		stream->read(size);
		BCoordArray* texCoords = new BCoordArray(size);
		stream->read(texCoords->data(), size * sizeof(BCoord));
		geometry->setTexCoords(texCoords);
		break;
	}
	case SIGN_ELEMENT:
	{
		BElement* element = (BElement*)read(chunk);
		geometry->addElement(element);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readTextual(const Chunk& chunk, BTextual* textual)
{
	switch (chunk.sign)
	{
	case SIGN_SIZE:
	{
		BSizef size;
		stream->read(size);
		textual->setSize(size);
		break;
	}
	case SIGN_SIZE_D:
	{
		BSized size;
		stream->read(size);
		textual->setSize(size);
		break;
	}
	case SIGN_ALIGN:
	{
		Align align = Align_None;
		stream->read(align);
		textual->setAlign(align);
		break;
	}
	case SIGN_FONT:
	{
		int fontSize = 0;
		stream->read(fontSize);
		BString family;
		stream->read(family);
		BFont* font = new BFont(family, fontSize);
		textual->setFont(font);
		break;
	}
	case SIGN_GLYPSIZE:
	{
		float glyphSize = 0.0f;
		stream->read(glyphSize);
		textual->setGlyphSize(glyphSize);
		break;
	}
	case SIGN_TEXT:
	{
		BString text;
		stream->read(text);
		textual->setText(text);
		break;
	}
	case SIGN_COLORS:
	{
		int size = 0;
		stream->read(size);
		BColorArray* colors = new BColorArray(size);
		stream->read(colors->data(), size * sizeof(BColor));
		textual->setColors(colors);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readParticle(const Chunk& chunk, BParticle* particle)
{
	return true;
}
bool member_BObcDocument::readElement(const Chunk& chunk, BElement* element)
{
	switch (chunk.sign)
	{
	case SIGN_PRIMITIVE:
	{
		Primitive primitive = Primitive_None;
		stream->read(primitive);
		element->setPrimitive(primitive);
		break;
	}
	case SIGN_FIRST:
	{
		int first = 0;
		stream->read(first);
		element->setFirst(first);
		break;
	}
	case SIGN_COUNT:
	{
		int count = 0;
		stream->read(count);
		element->setCount(count);
		break;
	}
	case SIGN_INDICES:
	{
		int size = 0;
		stream->read(size);
		BIndexArray* indices = new BIndexArray(size);
		stream->read(indices->data(), size * sizeof(int));
		element->setIndices(indices);
		break;
	}
	case SIGN_PIECES:
	{
		int size = 0;
		stream->read(size);
		BPieceArray* pieces = new BPieceArray(size);
		stream->read(pieces->data(), size * sizeof(BPiece));
		element->setPieces(pieces);
		break;
	}
	default:
		return false;
	}
	return true;
}

bool member_BObcDocument::readCube(const Chunk& chunk, BCube* cube)
{
	switch (chunk.sign)
	{
	case SIGN_LENGTH:
	{
		float length = 0.0f;
		stream->read(length);
		cube->setLength(length);
		break;
	}
	case SIGN_LENGTH_D:
	{
		double length = 0.0;
		stream->read(length);
		cube->setLength(length);
		break;
	}
	case SIGN_WIDTH:
	{
		float width = 0.0f;
		stream->read(width);
		cube->setWidth(width);
		break;
	}
	case SIGN_WIDTH_D:
	{
		double width = 0.0;
		stream->read(width);
		cube->setWidth(width);
		break;
	}
	case SIGN_HEIGHT:
	{
		float height = 0.0f;
		stream->read(height);
		cube->setHeight(height);
		break;
	}
	case SIGN_HEIGHT_D:
	{
		double height = 0.0;
		stream->read(height);
		cube->setHeight(height);
		break;
	}
	case SIGN_LENGTHSEGMENTS:
	{
		int lengthSegments = 0;
		stream->read(lengthSegments);
		cube->setLengthSegments(lengthSegments);
		break;
	}
	case SIGN_WIDTHSEGMENT:
	{
		int widthSegments = 0;
		stream->read(widthSegments);
		cube->setWidthSegments(widthSegments);
		break;
	}
	case SIGN_HEIGHTSEGMENT:
	{
		int heightSegments = 0;
		stream->read(heightSegments);
		cube->setHeightSegments(heightSegments);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readCone(const Chunk& chunk, BCone* cone)
{
	switch (chunk.sign)
	{
	case SIGN_RADIUS:
	{
		float radius = 0.0f;
		stream->read(radius);
		cone->setRadius(radius);
		break;
	}
	case SIGN_RADIUS_D:
	{
		double radius = 0.0;
		stream->read(radius);
		cone->setRadius(radius);
		break;
	}
	case SIGN_HEIGHT:
	{
		float height = 0.0f;
		stream->read(height);
		cone->setHeight(height);
		break;
	}
	case SIGN_HEIGHT_D:
	{
		double height = 0.0;
		stream->read(height);
		cone->setHeight(height);
		break;
	}
	case SIGN_SIDES:
	{
		int sides = 0;
		stream->read(sides);
		cone->setSides(sides);
		break;
	}
	case SIGN_SEGMENTS:
	{
		int segments = 0;
		stream->read(segments);
		cone->setSegments(segments);
		break;
	}
	case SIGN_RADIUSSEGMENTS:
	{
		int radiusSegments = 0;
		stream->read(radiusSegments);
		cone->setBottomSegments(radiusSegments);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readCylinder(const Chunk& chunk, BCylinder* cylinder)
{
	switch (chunk.sign)
	{
	case SIGN_RADIUS:
	{
		float radius = 0.0f;
		stream->read(radius);
		cylinder->setRadius(radius);
		break;
	}
	case SIGN_RADIUS_D:
	{
		double radius = 0.0;
		stream->read(radius);
		cylinder->setRadius(radius);
		break;
	}
	case SIGN_HEIGHT:
	{
		float height = 0.0f;
		stream->read(height);
		cylinder->setHeight(height);
		break;
	}
	case SIGN_HEIGHT_D:
	{
		double height = 0.0;
		stream->read(height);
		cylinder->setHeight(height);
		break;
	}
	case SIGN_SIDES:
	{
		int sides = 0;
		stream->read(sides);
		cylinder->setSides(sides);
		break;
	}
	case SIGN_HEIGHTSEGMENT:
	{
		int heightSegments = 0;
		stream->read(heightSegments);
		cylinder->setHeightSegments(heightSegments);
		break;
	}
	case SIGN_RADIUSSEGMENTS:
	{
		int radiusSegments = 0;
		stream->read(radiusSegments);
		cylinder->setRadiusSegments(radiusSegments);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readSphere(const Chunk& chunk, BSphere* sphere)
{
	switch (chunk.sign)
	{
	case SIGN_RADIUS:
	{
		float radius = 0.0f;
		stream->read(radius);
		sphere->setRadius(radius);
		break;
	}
	case SIGN_RADIUS_D:
	{
		double radius = 0.0;
		stream->read(radius);
		sphere->setRadius(radius);
		break;
	}
	case SIGN_SIDES:
	{
		int sides = 0;
		stream->read(sides);
		sphere->setSides(sides);
		break;
	}
	case SIGN_SEGMENTS:
	{
		int segments = 0;
		stream->read(segments);
		sphere->setSegments(segments);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readGeoSphere(const Chunk& chunk, BGeoSphere* geoSphere)
{
	switch (chunk.sign)
	{
	case SIGN_RADIUS:
	{
		float radius = 0.0f;
		stream->read(radius);
		geoSphere->setRadius(radius);
		break;
	}
	case SIGN_RADIUS_D:
	{
		double radius = 0.0;
		stream->read(radius);
		geoSphere->setRadius(radius);
		break;
	}
	case SIGN_SEGMENTS:
	{
		int segments = 0;
		stream->read(segments);
		geoSphere->setDivide(segments);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readTube(const Chunk& chunk, BTube* tube)
{
	switch (chunk.sign)
	{
	case SIGN_RADIUS:
	{
		float radius = 0.0f;
		stream->read(radius);
		tube->setRadius(radius);
		break;
	}
	case SIGN_RADIUS_D:
	{
		double radius = 0.0;
		stream->read(radius);
		tube->setRadius(radius);
		break;
	}
	case SIGN_HEIGHT:
	{
		float height = 0.0f;
		stream->read(height);
		tube->setHeight(height);
		break;
	}
	case SIGN_HEIGHT_D:
	{
		double height = 0.0;
		stream->read(height);
		tube->setHeight(height);
		break;
	}
	case SIGN_THICKNESS:
	{
		float thickness = 0.0f;
		stream->read(thickness);
		tube->setThickness(thickness);
		break;
	}
	case SIGN_THICKNESS_D:
	{
		double thickness = 0.0;
		stream->read(thickness);
		tube->setThickness(thickness);
		break;
	}
	case SIGN_SIDES:
	{
		int sides = 0;
		stream->read(sides);
		tube->setSides(sides);
		break;
	}
	case SIGN_HEIGHTSEGMENT:
	{
		int heightSegments = 0;
		stream->read(heightSegments);
		tube->setHeightSegments(heightSegments);
		break;
	}
	case SIGN_RADIUSSEGMENTS:
	{
		int radiusSegments = 0;
		stream->read(radiusSegments);
		tube->setRadiusSegments(radiusSegments);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readTorus(const Chunk& chunk, BTorus* torus)
{
	switch (chunk.sign)
	{
	case SIGN_RADIUS:
	{
		float radius = 0.0f;
		stream->read(radius);
		torus->setRadius(radius);
		break;
	}
	case SIGN_RADIUS_D:
	{
		double radius = 0.0;
		stream->read(radius);
		torus->setRadius(radius);
		break;
	}
	case SIGN_OUTERRADIUS:
	{
		float outerRadius = 0.0f;
		stream->read(outerRadius);
		torus->setOuterRadius(outerRadius);
		break;
	}
	case SIGN_OUTERRADIUS_D:
	{
		double outerRadius = 0.0;
		stream->read(outerRadius);
		torus->setOuterRadius(outerRadius);
		break;
	}
	case SIGN_SIDES:
	{
		int sides = 0;
		stream->read(sides);
		torus->setSides(sides);
		break;
	}
	case SIGN_SEGMENTS:
	{
		int divide = 0;
		stream->read(divide);
		torus->setDivide(divide);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readSurface(const Chunk& chunk, BSurface* surface)
{
	switch (chunk.sign)
	{
	case SIGN_QUAD:
	{
		BQuadf quad;
		stream->read(quad);
		surface->setQuadEdges(quad);
		break;
	}
	case SIGN_QUAD_D:
	{
		BQuadd quad;
		stream->read(quad);
		surface->setQuadEdges(quad);
		break;
	}
	case SIGN_HORSEGMENT:
	{
		int horSegment = 0;
		stream->read(horSegment);
		surface->setHorizontalSegment(horSegment);
		break;
	}
	case SIGN_VERSEGMENT:
	{
		int verSegment = 0;
		stream->read(verSegment);
		surface->setVerticalSegment(verSegment);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readTerrain(const Chunk& chunk, BTerrain* terrain)
{
	switch (chunk.sign)
	{
	case SIGN_ALIGN:
	{
		Align align = Align_None;
		stream->read(align);
		terrain->setAlign(align);
		break;
	}
	case SIGN_WIDTH:
	{
		float width = 0.0f;
		stream->read(width);
		terrain->setWidth(width);
		break;
	}
	case SIGN_WIDTH_D:
	{
		double width = 0.0;
		stream->read(width);
		terrain->setWidth(width);
		break;
	}
	case SIGN_HEIGHT:
	{
		float height = 0.0f;
		stream->read(height);
		terrain->setHeight(height);
		break;
	}
	case SIGN_HEIGHT_D:
	{
		double height = 0.0;
		stream->read(height);
		terrain->setHeight(height);
		break;
	}
	case SIGN_ELEVATION:
	{
		int rows = 0;
		int columns = 0;
		stream->read(rows);
		stream->read(columns);
		BFloatTable elevation(rows, columns);
		stream->read(elevation.data(), elevation.size() * sizeof(float));
		terrain->setElevation(elevation);
		break;
	}
	case SIGN_ELEVATION_D:
	{
		int rows = 0;
		int columns = 0;
		stream->read(rows);
		stream->read(columns);
		BDoubleTable elevation(rows, columns);
		stream->read(elevation.data(), elevation.size() * sizeof(double));
		terrain->setElevation(elevation);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readCapsule(const Chunk& chunk, BCapsule* capsule)
{
	switch (chunk.sign)
	{
	case SIGN_RADIUS:
	{
		float radius = 0.0f;
		stream->read(radius);
		capsule->setRadius(radius);
		break;
	}
	case SIGN_RADIUS_D:
	{
		double radius = 0.0;
		stream->read(radius);
		capsule->setRadius(radius);
		break;
	}
	case SIGN_HEIGHT:
	{
		float height = 0.0f;
		stream->read(height);
		capsule->setHeight(height);
		break;
	}
	case SIGN_HEIGHT_D:
	{
		double height = 0.0;
		stream->read(height);
		capsule->setHeight(height);
		break;
	}
	case SIGN_SIDES:
	{
		int sides = 0;
		stream->read(sides);
		capsule->setSides(sides);
		break;
	}
	case SIGN_HEIGHTSEGMENT:
	{
		int heightSegments = 0;
		stream->read(heightSegments);
		capsule->setHeightSegments(heightSegments);
		break;
	}
	case SIGN_RADIUSSEGMENTS:
	{
		int radiusSegments = 0;
		stream->read(radiusSegments);
		capsule->setRadiusSegments(radiusSegments);
		break;
	}
	default:
		return false;
	}
	return true;
}

bool member_BObcDocument::readMaterial(const Chunk& chunk, BMaterial* material)
{
	switch (chunk.sign)
	{
	case SIGN_AMBIENT:
	{
		BColor ambient;
		stream->read(ambient);
		material->setAmbient(ambient);
		break;
	}
	case SIGN_DIFFUSE:
	{
		BColor diffuse;
		stream->read(diffuse);
		material->setDiffuse(diffuse);
		break;
	}
	case SIGN_SPECULAR:
	{
		BColor specular;
		stream->read(specular);
		material->setSpecular(specular);
		break;
	}
	case SIGN_EMISSION:
	{
		BColor emission;
		stream->read(emission);
		material->setEmission(emission);
		break;
	}
	case SIGN_SHININESS:
	{
		BByte shininess = 0;
		stream->read(shininess);
		material->setShininess(shininess);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readTexture(const Chunk& chunk, BTexture* texture)
{
	switch (chunk.sign)
	{
	case SIGN_BLEND:
	{
		BTexture::Blend blend = BTexture::Blend_None;
		stream->read(blend);
		texture->setBlend(blend);
		break;
	}
	case SIGN_WRAP:
	{
		BTexture::Wrap wrap = BTexture::Wrap_None;
		stream->read(wrap);
		texture->setWrap(wrap);
		break;
	}
	case SIGN_FILTER:
	{
		BTexture::Filter filter = BTexture::Filter_None;
		stream->read(filter);
		texture->setFilter(filter);
		break;
	}
	case SIGN_MIPMAP:
	{
		bool mipmap = false;
		stream->read(mipmap);
		texture->setMipmap(mipmap);
		break;
	}
	case SIGN_BLENDCOLOR:
	{
		BColor blendColor;
		stream->read(blendColor);
		texture->setBlendColor(blendColor);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readImage(const Chunk& chunk, BImage* image)
{
	switch (chunk.sign)
	{
	case SIGN_FILENAME:
	{
		BString fileName;
		stream->read(fileName);
		image->setFileName(fileName);
		if (chunk.end > (unsigned int)stream->offset())
		{
			if (BReadWrite* rw = FindReadWrite(fileName))
			{
				int size = chunk.end - stream->offset();
				BBuffer buffer(size);
				stream->read(buffer.bytes(), size);
				if (rw->read(buffer, image))
					break;
				message() << "OBC Error : Read image bytes failed : " << fileName;
			}
		}
		else
		{
			if (ReadFile(fileName, image))
				break;
			BString absFileName = BApplication::CurrentPath();
			absFileName << '/' << fileName;
			if (ReadFile(absFileName, image))
				break;
			message() << "OBC Error : Read image file failed : " << fileName;
		}
		break;
	}
	case SIGN_FORMAT:
	{
		Format format = Format_None;
		stream->read(format);
		image->setFormat(format);
		break;
	}
	case SIGN_SIZE:
	{
		BSize size;
		stream->read(size);
		image->setSize(size);
		break;
	}
	case SIGN_PIXELS:
	{
		int size = 0;
		stream->read(size);
		BByteArray* pixels = new BByteArray(size);
		stream->read(pixels->data(), size);
		image->setPixels(pixels);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readPixmap(const Chunk& chunk, BPixmap* pixmap)
{
	switch (chunk.sign)
	{
	case SIGN_BLEND:
	{
		BTexture::Blend blend = BTexture::Blend_None;
		stream->read(blend);
		pixmap->setBlend(blend);
		break;
	}
	case SIGN_WRAP:
	{
		BTexture::Wrap wrap = BTexture::Wrap_None;
		stream->read(wrap);
		pixmap->setWrap(wrap);
		break;
	}
	case SIGN_FILTER:
	{
		BTexture::Filter filter = BTexture::Filter_None;
		stream->read(filter);
		pixmap->setFilter(filter);
		break;
	}
	case SIGN_MIPMAP:
	{
		bool mipmap = false;
		stream->read(mipmap);
		pixmap->setMipmap(mipmap);
		break;
	}
	case SIGN_BLENDCOLOR:
	{
		BColor blendColor;
		stream->read(blendColor);
		pixmap->setBlendColor(blendColor);
		break;
	}
	case SIGN_SIZE:
	{
		BSize size;
		stream->read(size);
		pixmap->setSize(size);
		break;
	}
	case SIGN_BACKGROUND:
	{
		BColor background;
		stream->read(background);
		pixmap->setColor(background);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readProgram(const Chunk& chunk, BProgram* program)
{
	switch (chunk.sign)
	{
	case SIGN_SHADER:
	{
		BShader* shader = (BShader*)read(chunk);
		program->addShader(shader);
		break;
	}
	case SIGN_UNIFORM:
	{
		BUniform* uniform = (BUniform*)read(chunk);
		program->addUniform(uniform);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readShader(const Chunk& chunk, BShader* shader)
{
	switch (chunk.sign)
	{
	case SIGN_TYPE:
	{
		BShader::Type type = BShader::Type_None;
		stream->read(type);
		shader->setType(type);
		break;
	}
	case SIGN_TEXT:
	{
		BString text;
		stream->read(text);
		shader->setText(text);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readUniform(const Chunk& chunk, BUniform* uniform)
{
	switch (chunk.sign)
	{
	case SIGN_SIGN:
	{
		BString sign;
		stream->read(sign);
		uniform->setSign(sign);
		break;
	}
	case SIGN_TYPE:
	{
		BUniform::Type type = BUniform::Type_None;
		stream->read(type);
		uniform->setType(type);
		break;
	}
	case SIGN_SIZE:
	{
		int size = 0;
		stream->read(size);
		uniform->setSize(size);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readPhysics(const Chunk& chunk, BPhysics* physics)
{
	switch (chunk.sign)
	{
	case SIGN_MASS:
	{
		float mass = 0;
		stream->read(mass);
		physics->setMass(mass);
		break;
	}
	case SIGN_MASS_D:
	{
		double mass = 0;
		stream->read(mass);
		physics->setMass(mass);
		break;
	}
	case SIGN_FRICTION:
	{
		float friction = 0;
		stream->read(friction);
		physics->setFriction(friction);
		break;
	}
	case SIGN_FRICTION_D:
	{
		double friction = 0;
		stream->read(friction);
		physics->setFriction(friction);
		break;
	}
	case SIGN_ELASTANE:
	{
		float elastane = 0;
		stream->read(elastane);
		physics->setElastane(elastane);
		break;
	}
	case SIGN_ELASTANE_D:
	{
		double elastane = 0;
		stream->read(elastane);
		physics->setElastane(elastane);
		break;
	}
	case SIGN_FORCE:
	{
		BVectorf force;
		stream->read(force);
		physics->setForce(force);
		break;
	}
	case SIGN_FORCE_D:
	{
		BVectord force;
		stream->read(force);
		physics->setForce(force);
		break;
	}
	case SIGN_GRAVITY:
	{
		BVectorf gravity;
		stream->read(gravity);
		physics->setGravity(gravity);
		break;
	}
	case SIGN_GRAVITY_D:
	{
		BVectord gravity;
		stream->read(gravity);
		physics->setGravity(gravity);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readScript(const Chunk& chunk, BScript* script)
{
	switch (chunk.sign)
	{
	case SIGN_SOURCE:
	{
		BSource* source = (BSource*)read(chunk);
		script->insertSource(source);
		break;
	}
	case SIGN_SEQUENCE:
	{
		int size = 0;
		stream->read(size);
		BExpHolderArray sequence(size);
		Chunk expChunk;
		for (int i = 0; i < size; i++)
		{
			sequence[i] = new BExp();
			readBeginChunk(expChunk, chunk.end);
			readExp(expChunk, sequence[i]);
			readEndChunk(expChunk);
		}
		script->setSequence(sequence);
		break;
	}
	default:
		return false;
	}
	return true;
}
bool member_BObcDocument::readSource(const Chunk& chunk, BSource* source)
{
	return true;
}
bool member_BObcDocument::readExp(const Chunk& chunk, BExp* exp)
{
	switch (chunk.sign)
	{
	case SIGN_NAME:
		stream->read(exp->name);
		break;
	case SIGN_SYNTAX:
		stream->read(exp->syntax);
		break;
	case SIGN_INFORMATION:
		stream->read(exp->info);
		break;
	case SIGN_TYPE:
		stream->read(exp->type);
		break;
	case SIGN_VALUE:
	{
		char c = 0;
		stream->read(c);
		if (c == 'c')
		{
			exp->value.fill<char>();
			stream->read((char&)exp->value);
		}
		else if (c == 'b')
		{
			exp->value.fill<unsigned char>();
			stream->read((unsigned char&)exp->value);
		}
		else if (c == 's')
		{
			exp->value.fill<short>();
			stream->read((short&)exp->value);
		}
		else if (c == 't')
		{
			exp->value.fill<unsigned short>();
			stream->read((unsigned short&)exp->value);
		}
		else if (c == 'i')
		{
			exp->value.fill<int>();
			stream->read((int&)exp->value);
		}
		else if (c == 'u')
		{
			exp->value.fill<unsigned int>();
			stream->read((unsigned int&)exp->value);
		}
		else if (c == 'l')
		{
			exp->value.fill<long long>();
			stream->read((long long&)exp->value);
		}
		else if (c == 'm')
		{
			exp->value.fill<unsigned long long>();
			stream->read((unsigned long long&)exp->value);
		}
		else if (c == 'f')
		{
			exp->value.fill<float>();
			stream->read((float&)exp->value);
		}
		else if (c == 'd')
		{
			exp->value.fill<double>();
			stream->read((double&)exp->value);
		}
		else if (c == 's')
		{
			exp->value.fill<BString>();
			stream->read((BString&)exp->value);
		}
		break;
	}
	case SIGN_EXP:
	{
		BExp* child = new BExp();
		readExp(chunk, exp);
		exp->params.append(child);
		break;
	}
	default:
		return false;
	}
	return true;
}

bool member_BObcDocument::writeWidgetData(const BWidget* widget)
{
	return false;
}

bool member_BObcDocument::writeObject(const BObject* object)
{
	{
		AutoChunk chunk(this, SIGN_NAME);
		stream->write(object->name());
	}
	{
		AutoChunk chunk(this, SIGN_ENABLED);
		stream->write(object->enabled());
	}
	return true;
}
bool member_BObcDocument::writeScene(const BScene* scene)
{
	{
		AutoChunk chunk(this, SIGN_OPTIMIZED);
		bool optimized = scene->optimized();
		stream->write(optimized);
	}
	for (int i = 0; i < scene->shapeCount(); i++)
	{
		const BShape* shape = scene->shape(i);
		if (!write(shape))
		{
			return false;
		}
	}
	for (int i = 0; i < scene->nodeCount(); i++)
	{
		const BNode* node = scene->node(i);
		if (!write(node))
		{
			return false;
		}
	}
	for (int i = 0; i < scene->constraintCount(); i++)
	{
		const BConstraint* constraint = scene->constraint(i);
		if (!write(constraint))
		{
			return false;
		}
	}
	for (int i = 0; i < scene->groupCount(); i++)
	{
		const BGroup* group = scene->group(i);
		if (!write(group))
		{
			return false;
		}
	}
	return true;
}
bool member_BObcDocument::writeGroup(const BGroup* group)
{
	for (int i = 0; i < group->shapeCount(); i++)
	{
		const BShape* shape = group->shape(i);
		if (!write(shape))
		{
			return false;
		}
	}
	for (int i = 0; i < group->nodeCount(); i++)
	{
		const BNode* node = group->node(i);
		if (!write(node))
		{
			return false;
		}
	}
	for (int i = 0; i < group->childCount(); i++)
	{
		const BGroup* childGroup = group->child(i);
		if (!write(childGroup))
		{
			return false;
		}
	}
	for (int i = 0; i < group->constraintCount(); i++)
	{
		const BConstraint* constraint = group->constraint(i);
		if (!write(constraint))
		{
			return false;
		}
	}
	return true;
}
bool member_BObcDocument::writeNode(const BNode* node)
{
	{
		AutoChunk chunk(this, SIGN_VISIBLE);
		stream->write(node->visible());
	}
	{
		AutoChunk chunk(this, SIGN_OPTIMIZED);
		stream->write(node->optimized());
	}
	{
		AutoChunk chunk(this, SIGN_MATRIX);
		stream->write(node->matrix());
	}
	if (BPhysics* physics = node->physics())
	{
		write(physics);
	}
	for (int i = 0; i < node->shapeCount(); i++)
	{
		const BShape* shape = node->shape(i);
		write(shape);
	}
	return true;
}
bool member_BObcDocument::writeLight(const BLight* light)
{
	{
		AutoChunk chunk(this, SIGN_TYPE);
		BLight::Type type = light->type();
		stream->write(type);
	}
	{
		AutoChunk chunk(this, SIGN_AMBIENT);
		BColor ambient = light->ambient();
		stream->write(ambient);
	}
	{
		AutoChunk chunk(this, SIGN_DIFFUSE);
		BColor diffuse = light->diffuse();
		stream->write(diffuse);
	}
	{
		AutoChunk chunk(this, SIGN_SPECULAR);
		BColor specular = light->specular();
		stream->write(specular);
	}
	{
		AutoChunk chunk(this, SIGN_ATTENUATION);
		float attenuation = light->attenuation();
		stream->write(attenuation);
	}
	{
		AutoChunk chunk(this, SIGN_ATTENUATION2);
		float attenuation2 = light->attenuation2();
		stream->write(attenuation2);
	}
	{
		AutoChunk chunk(this, SIGN_CUTOFF);
		float cutoff = light->cutoff();
		stream->write(cutoff);
	}
	{
		AutoChunk chunk(this, SIGN_EXPONENT);
		float exponent = light->exponent();
		stream->write(exponent);
	}
	{
		AutoChunk chunk(this, SIGN_DIRECTION);
		BVector direction = light->direction();
		stream->write(direction);
	}

	return true;
}
bool member_BObcDocument::writeCamera(const BCamera* camera)
{
	{
		AutoChunk chunk(this, SIGN_ORTHO);
		bool ortho = camera->ortho();
		stream->write(ortho);
	}
	{
		AutoChunk chunk(this, SIGN_CENTER);
		BVector center = camera->center();
		stream->write(center);
	}
	{
		AutoChunk chunk(this, SIGN_UP);
		BVector up = camera->up();
		stream->write(up);
	}
	{
		AutoChunk chunk(this, SIGN_NEAR);
		double near = camera->near();
		stream->write(near);
	}
	{
		AutoChunk chunk(this, SIGN_FAR);
		double far = camera->far();
		stream->write(far);
	}
	{
		AutoChunk chunk(this, SIGN_FOVY);
		double fovy = camera->fovy();
		stream->write(fovy);
	}
	{
		AutoChunk chunk(this, SIGN_ASPECT);
		double aspect = camera->aspect();
		stream->write(aspect);
	}
	{
		AutoChunk chunk(this, SIGN_LENSSIZE);
		double lensWidth = camera->lensWidth();
		stream->write(lensWidth);
		double lensHeight = camera->lensHeight();
		stream->write(lensHeight);
	}
	{
		AutoChunk chunk(this, SIGN_PIXELSIZE);
		int pixelWidth = camera->pixelWidth();
		stream->write(pixelWidth);
		int pixelHeight = camera->pixelHeight();
		stream->write(pixelHeight);
	}
	{
		AutoChunk chunk(this, SIGN_PIXELPOLICY);
		Policy pixelPolicy = camera->pixelSizePolicy();
		stream->write(pixelPolicy);
	}
	{
		AutoChunk chunk(this, SIGN_BACKGROUND);
		const BColor& color = camera->color();
		stream->write(color);
	}
	return true;
}
bool member_BObcDocument::writeBillboard(const BBillboard* billboard)
{
	const BQuad& quad = billboard->quad();
	{
		AutoChunk chunk(this, SIGN_QUAD);
		stream->write(quad);
	}
	const BVector& axis = billboard->axis();
	{
		AutoChunk chunk(this, SIGN_AXIS);
		stream->write(axis);
	}
	return true;
}
bool member_BObcDocument::writeConstraint(const BConstraint* constraint)
{
	if (BNode* nodeA = constraint->nodeA())
	{
		AutoChunk chunk(this, SIGN_NODEA);
		int idA = writeObjectMap(nodeA);
		stream->write(idA);
	}
	{
		AutoChunk chunk(this, SIGN_POINTA);
		const BVector& pointA = constraint->pointA();
		stream->write(pointA);
	}
	if (BNode* nodeB = constraint->nodeB())
	{
		AutoChunk chunk(this, SIGN_NODEB);
		int idB = writeObjectMap(nodeB);
		stream->write(idB);
	}
	{
		AutoChunk chunk(this, SIGN_POINTB);
		const BVector& pointB = constraint->pointB();
		stream->write(pointB);
	}
	{
		AutoChunk chunk(this, SIGN_INNER_COLLIBLE);
		bool innerCollible = constraint->innerCollible();
		stream->write(innerCollible);
	}
	{
		AutoChunk chunk(this, SIGN_BREAK_IMPULSE);
		BReal breakImpulse = constraint->breakImpulse();
		stream->write(breakImpulse);
	}
	return true;
}
bool member_BObcDocument::writePointConstraint(const BPointConstraint* pointConstraint)
{
	{
		AutoChunk chunk(this, SIGN_FLAGS);
		BPointConstraint::Flags flags = pointConstraint->flags();
		stream->write(flags);
	}
	{
		AutoChunk chunk(this, SIGN_ERP);
		BReal erp = pointConstraint->erp();
		stream->write(erp);
	}
	{
		AutoChunk chunk(this, SIGN_CFM);
		BReal cfm = pointConstraint->cfm();
		stream->write(cfm);
	}
	{
		AutoChunk chunk(this, SIGN_TAU);
		BReal tau = pointConstraint->tau();
		stream->write(tau);
	}
	{
		AutoChunk chunk(this, SIGN_DAMPING);
		BReal damping = pointConstraint->damping();
		stream->write(damping);
	}
	{
		AutoChunk chunk(this, SIGN_IMPULSECLAMP);
		BReal impulseClamp = pointConstraint->impulseClamp();
		stream->write(impulseClamp);
	}
	return true;
}
bool member_BObcDocument::writeHingeConstraint(const BHingeConstraint* hingeConstraint)
{
	return false;
}
bool member_BObcDocument::writeSliderConstraint(const BSliderConstraint* constraint)
{
	{
		AutoChunk chunk(this, SIGN_AXISA);
		const BVector& axisA = constraint->axisA();
		stream->write(axisA);
	}
	{
		AutoChunk chunk(this, SIGN_AXISB);
		const BVector& axisB = constraint->axisB();
		stream->write(axisB);
	}
	{
		AutoChunk chunk(this, SIGN_LINEAR_LIMIT);
		const BRealRange& linearLimit = constraint->linearLimit();
		stream->write(linearLimit);
	}
	{
		AutoChunk chunk(this, SIGN_ANGLE_LIMIT);
		const BRealRange& angleLimit = constraint->angleLimit();
		stream->write(angleLimit);
	}

	return true;
}
bool member_BObcDocument::writeConearConstraint(const BConearConstraint* conearConstraint)
{
	return false;
}
bool member_BObcDocument::writeSixdofConstraint(const BSixdofConstraint* sixdofConstraint)
{
	return false;
}

bool member_BObcDocument::writeShape(const BShape* shape)
{
	{
		bool lighting = shape->lighting();
		AutoChunk chunk(this, SIGN_LIGHTING);
		stream->write(lighting);
	}
	{
		bool cullback = shape->cullback();
		AutoChunk chunk(this, SIGN_CULLBACK);
		stream->write(cullback);
	}
	{
		bool depthTest = shape->depthTest();
		AutoChunk chunk(this, SIGN_DEPTHTEST);
		stream->write(depthTest);
	}
	{
		bool pointSmooth = shape->pointSmooth();
		AutoChunk chunk(this, SIGN_POINTSMOOTH);
		stream->write(pointSmooth);
	}
	{
		bool lineSmooth = shape->lineSmooth();
		AutoChunk chunk(this, SIGN_LINESMOOTH);
		stream->write(lineSmooth);
	}
	{
		bool polygonSmooth = shape->polygonSmooth();
		AutoChunk chunk(this, SIGN_POLYGONSMOOTH);
		stream->write(polygonSmooth);
	}
	{
		int lineWidth = shape->lineWidth();
		AutoChunk chunk(this, SIGN_LINEWIDTH);
		stream->write(lineWidth);
	}
	{
		int pointSize = shape->pointSize();
		AutoChunk chunk(this, SIGN_POINTSIZE);
		stream->write(pointSize);
	}
	{
		char polyMode = (char)shape->polyMode();
		AutoChunk chunk(this, SIGN_POLYGONMODE);
		stream->write(polyMode);
	}
	{
		bool transparent = shape->transparent();
		AutoChunk chunk(this, SIGN_TRANSPARENT);
		stream->write(transparent);
	}
	{
		AutoChunk chunk(this, SIGN_MATRIX);
		stream->write(shape->matrix());
	}
	{
		AutoChunk chunk(this, SIGN_COLOR);
		stream->write(shape->color());
	}
	if (BMaterial* material = shape->material())
	{
		write(material);
	}
	if (BTexture* texture = shape->texture())
	{
		write(texture);
	}
	if (BProgram* program = shape->program())
	{
		write(program);
	}
	return true;
}
bool member_BObcDocument::writeMesh(const BMesh* mesh)
{
	{
		AutoChunk chunk(this, SIGN_OPTIMIZED);
		stream->write(mesh->optimized());
	}
	if (const BVectorArray* vertices = mesh->vertices())
	{
		AutoChunk chunk(this, SIGN_VERTICES);
		int size = vertices->size();
		stream->write(size);
		stream->write(vertices->data(), size * sizeof(BVector));
	}
	if (const BVectorArray* normals = mesh->normals())
	{
		AutoChunk chunk(this, SIGN_NORMALS);
		int size = normals->size();
		stream->write(size);
		stream->write(normals->data(), size * sizeof(BVector));
	}
	if (const BColorArray* colors = mesh->colors())
	{
		AutoChunk chunk(this, SIGN_COLORS);
		int size = colors->size();
		stream->write(size);
		stream->write(colors->data(), size * sizeof(BColor));
	}
	if (const BCoordArray* texCoords = mesh->texCoords())
	{
		AutoChunk chunk(this, SIGN_TEXCOORDS);
		int size = texCoords->size();
		stream->write(size);
		stream->write(texCoords->data(), size * sizeof(BCoord));
	}
	if (const BFaceArray* faces = mesh->faces())
	{
		AutoChunk chunk(this, SIGN_FACES);
		int size = faces->size();
		stream->write(size);
		stream->write(faces->data(), size * 12);
	}
	return true;
}
bool member_BObcDocument::writeGeometry(const BGeometry* geometry)
{
	{
		AutoChunk chunk(this, SIGN_OPTIMIZED);
		bool optimized = geometry->optimized();
		stream->write(optimized);
	}
	if (const BVectorArray* vertices = geometry->vertices())
	{
		AutoChunk chunk(this, SIGN_VERTICES);
		int size = vertices->size();
		stream->write(size);
		stream->write(vertices->data(), size * sizeof(BVector));
	}
	if (const BVectorArray* normals = geometry->normals())
	{
		AutoChunk chunk(this, SIGN_NORMALS);
		int size = normals->size();
		stream->write(size);
		stream->write(normals->data(), size * sizeof(BVector));
	}
	if (const BColorArray* colors = geometry->colors())
	{
		AutoChunk chunk(this, SIGN_COLORS);
		int size = colors->size();
		stream->write(size);
		stream->write(colors->data(), size * sizeof(BColor));
	}
	if (const BCoordArray* texCoords = geometry->texCoords())
	{
		AutoChunk chunk(this, SIGN_TEXCOORDS);
		int size = texCoords->size();
		stream->write(size);
		stream->write(texCoords->data(), size * sizeof(BCoord));
	}
	for (int i = 0; i < geometry->elementCount(); i++)
	{
		const BElement* element = geometry->element(i);
		write(element);
	}
	return true;
}
bool member_BObcDocument::writeTextual(const BTextual* textual)
{
	{
		AutoChunk chunk(this, SIGN_QUAD);
		const BQuad& quad = textual->quad();
		stream->write(quad);
	}
	{
		AutoChunk chunk(this, SIGN_ALIGN);
		Align align = textual->align();
		stream->write(align);
	}
	if (const BFont* font = textual->font())
	{
		AutoChunk chunk(this, SIGN_FONT);
		stream->write(font->family());
		stream->write(font->size());
	}
	{
		AutoChunk chunk(this, SIGN_GLYPSIZE);
		BReal glyphSize = textual->glyphSize();
		stream->write(glyphSize);
	}
	{
		AutoChunk chunk(this, SIGN_TEXT);
		const BString& text = textual->text();
		stream->write(text);
	}
	if (const BColorArray* colors = textual->colors())
	{
		AutoChunk chunk(this, SIGN_COLORS);
		stream->write(colors->size());
		stream->write(colors->data(), colors->size() * sizeof(BColor));
	}
	return true;
}
bool member_BObcDocument::writeParticle(const BParticle* particle)
{
	return false;
}
bool member_BObcDocument::writeElement(const BElement* element)
{
	{
		AutoChunk chunk(this, SIGN_PRIMITIVE);
		int primitive = element->primitive();
		stream->write(primitive);
	}
	{
		AutoChunk chunk(this, SIGN_FIRST);
		int first = element->first();
		stream->write(first);
	}
	{
		AutoChunk chunk(this, SIGN_COUNT);
		int count = element->count();
		stream->write(count);
	}
	BIndexArray* indices = element->indices();
	if (indices)
	{
		AutoChunk chunk(this, SIGN_INDICES);
		int size = indices->size();
		stream->write(size);
		stream->write(indices->data(), size * 4);
	}
	BPieceArray* pieces = element->pieces();
	if (pieces)
	{
		AutoChunk chunk(this, SIGN_PIECES);
		int size = pieces->size();
		stream->write(size);
		stream->write(pieces->data(), size * sizeof(BPiece));
	}
	return true;
}
bool member_BObcDocument::writeCube(const BCube* cube)
{
	{
		AutoChunk chunk(this, SIGN_LENGTH);
		BReal length = cube->length();
		stream->write(length);
	}
	{
		AutoChunk chunk(this, SIGN_WIDTH);
		BReal width = cube->width();
		stream->write(width);
	}
	{
		AutoChunk chunk(this, SIGN_HEIGHT);
		BReal height = cube->height();
		stream->write(height);
	}
	{
		AutoChunk chunk(this, SIGN_LENGTHSEGMENTS);
		int lengthSegments = cube->lengthSegments();
		stream->write(lengthSegments);
	}
	{
		AutoChunk chunk(this, SIGN_WIDTHSEGMENT);
		int widthSegments = cube->widthSegments();
		stream->write(widthSegments);
	}
	{
		AutoChunk chunk(this, SIGN_HEIGHTSEGMENT);
		int heightSegments = cube->heightSegments();
		stream->write(heightSegments);
	}
	return true;
}
bool member_BObcDocument::writeCone(const BCone* cone)
{
	{
		AutoChunk chunk(this, SIGN_RADIUS);
		BReal radius = cone->radius();
		stream->write(radius);
	}
	{
		AutoChunk chunk(this, SIGN_HEIGHT);
		BReal height = cone->height();
		stream->write(height);
	}
	{
		AutoChunk chunk(this, SIGN_SIDES);
		int sides = cone->sides();
		stream->write(sides);
	}
	{
		AutoChunk chunk(this, SIGN_SEGMENTS);
		int segments = cone->segments();
		stream->write(segments);
	}
	{
		AutoChunk chunk(this, SIGN_RADIUSSEGMENTS);
		int radiusSegments = cone->radiusSegments();
		stream->write(radiusSegments);
	}
	return true;
}
bool member_BObcDocument::writeCylinder(const BCylinder* cylinder)
{
	{
		AutoChunk chunk(this, SIGN_RADIUS);
		BReal radius = cylinder->radius();
		stream->write(radius);
	}
	{
		AutoChunk chunk(this, SIGN_HEIGHT);
		BReal height = cylinder->height();
		stream->write(height);
	}
	{
		AutoChunk chunk(this, SIGN_SIDES);
		int sides = cylinder->sides();
		stream->write(sides);
	}
	{
		AutoChunk chunk(this, SIGN_HEIGHTSEGMENT);
		int heightSegments = cylinder->heightSegments();
		stream->write(heightSegments);
	}
	{
		AutoChunk chunk(this, SIGN_RADIUSSEGMENTS);
		int radiusSegments = cylinder->radiusSegments();
		stream->write(radiusSegments);
	}
	return true;
}
bool member_BObcDocument::writeSphere(const BSphere* sphere)
{
	{
		AutoChunk chunk(this, SIGN_RADIUS);
		BReal radius = sphere->radius();
		stream->write(radius);
	}
	{
		AutoChunk chunk(this, SIGN_SIDES);
		int sides = sphere->sides();
		stream->write(sides);
	}
	{
		AutoChunk chunk(this, SIGN_SEGMENTS);
		int segments = sphere->segments();
		stream->write(segments);
	}
	return true;
}
bool member_BObcDocument::writeGeoSphere(const BGeoSphere* geoSphere)
{
	{
		AutoChunk chunk(this, SIGN_RADIUS);
		BReal radius = geoSphere->radius();
		stream->write(radius);
	}
	{
		AutoChunk chunk(this, SIGN_SEGMENTS);
		int segments = geoSphere->divide();
		stream->write(segments);
	}
	return true;
}
bool member_BObcDocument::writeTube(const BTube* tube)
{
	{
		AutoChunk chunk(this, SIGN_RADIUS);
		BReal radius = tube->radius();
		stream->write(radius);
	}
	{
		AutoChunk chunk(this, SIGN_HEIGHT);
		BReal height = tube->height();
		stream->write(height);
	}
	{
		AutoChunk chunk(this, SIGN_SIDES);
		int sides = tube->sides();
		stream->write(sides);
	}
	{
		AutoChunk chunk(this, SIGN_HEIGHTSEGMENT);
		int heightSegments = tube->heightSegments();
		stream->write(heightSegments);
	}
	{
		AutoChunk chunk(this, SIGN_RADIUSSEGMENTS);
		int radiusSegments = tube->radiusSegments();
		stream->write(radiusSegments);
	}
	{
		AutoChunk chunk(this, SIGN_THICKNESS);
		BReal thickness = tube->thickness();
		stream->write(thickness);
	}
	return true;
}
bool member_BObcDocument::writeTorus(const BTorus* torus)
{
	{
		AutoChunk chunk(this, SIGN_RADIUS);
		BReal radius = torus->radius();
		stream->write(radius);
	}
	{
		AutoChunk chunk(this, SIGN_OUTERRADIUS);
		BReal outerRadius = torus->outerRadius();
		stream->write(outerRadius);
	}
	{
		AutoChunk chunk(this, SIGN_SIDES);
		int sides = torus->sides();
		stream->write(sides);
	}
	{
		AutoChunk chunk(this, SIGN_SEGMENTS);
		int divide = torus->divide();
		stream->write(divide);
	}
	return true;
}
bool member_BObcDocument::writeSurface(const BSurface* surface)
{
	{
		AutoChunk chunk(this, SIGN_QUAD);
		BQuad quad = surface->quadEdges();
		stream->write(quad);
	}
	{
		AutoChunk chunk(this, SIGN_HORSEGMENT);
		int horSegment = surface->horizontalSegment();
		stream->write(horSegment);
	}
	{
		AutoChunk chunk(this, SIGN_VERSEGMENT);
		int verSegment = surface->verticalSegment();
		stream->write(verSegment);
	}
	return true;
}
bool member_BObcDocument::writeTerrain(const BTerrain* terrain)
{
	{
		AutoChunk chunk(this, SIGN_ALIGN);
		Align align = terrain->align();
		stream->write(align);
	}
	{
		AutoChunk chunk(this, SIGN_WIDTH);
		BReal width = terrain->width();
		stream->write(width);
	}
	{
		AutoChunk chunk(this, SIGN_HEIGHT);
		BReal height = terrain->height();
		stream->write(height);
	}
	const BRealTable& elevation = terrain->elevation();
	if (elevation.size())
	{
		AutoChunk chunk(this, SIGN_ELEVATION);
		stream->write(elevation.row());
		stream->write(elevation.column());
		stream->write(elevation.data(), elevation.size() * sizeof(BReal));
	}
	return true;
}
bool member_BObcDocument::writeCapsule(const BCapsule* capsule)
{
	{
		AutoChunk chunk(this, SIGN_RADIUS);
		BReal radius = capsule->radius();
		stream->write(radius);
	}
	{
		AutoChunk chunk(this, SIGN_HEIGHT);
		BReal height = capsule->height();
		stream->write(height);
	}
	{
		AutoChunk chunk(this, SIGN_SIDES);
		int sides = capsule->sides();
		stream->write(sides);
	}
	{
		AutoChunk chunk(this, SIGN_HEIGHTSEGMENT);
		int heightSegments = capsule->heightSegments();
		stream->write(heightSegments);
	}
	{
		AutoChunk chunk(this, SIGN_RADIUSSEGMENTS);
		int radiusSegments = capsule->radiusSegments();
		stream->write(radiusSegments);
	}
	return true;
}

bool member_BObcDocument::writeMaterial(const BMaterial* material)
{
	{
		AutoChunk chunk(this, SIGN_AMBIENT);
		BColor ambient = material->ambient();
		stream->write(ambient);
	}
	{
		AutoChunk chunk(this, SIGN_DIFFUSE);
		BColor diffuse = material->diffuse();
		stream->write(diffuse);
	}
	{
		AutoChunk chunk(this, SIGN_SPECULAR);
		BColor specular = material->specular();
		stream->write(specular);
	}
	{
		AutoChunk chunk(this, SIGN_EMISSION);
		BColor emission = material->emission();
		stream->write(emission);
	}
	{
		AutoChunk chunk(this, SIGN_SHININESS);
		BByte shininess = material->shininess();
		stream->write(shininess);
	}
	return true;
}
bool member_BObcDocument::writeTexture(const BTexture* texture)
{
	{
		AutoChunk chunk(this, SIGN_BLEND);
		int blend = texture->blend();
		stream->write(blend);
	}
	{
		AutoChunk chunk(this, SIGN_BLENDCOLOR);
		BColor color = texture->blendColor();
		stream->write(color);
	}
	{
		AutoChunk chunk(this, SIGN_FILTER);
		int filter = texture->filter();
		stream->write(filter);
	}
	{
		AutoChunk chunk(this, SIGN_WRAP);
		int wrap = texture->wrap();
		stream->write(wrap);
	}
	{
		AutoChunk chunk(this, SIGN_MIPMAP);
		bool mipmap = texture->mipmap();
		stream->write(mipmap);
	}
	return true;
}
bool member_BObcDocument::writeImage(const BImage* image)
{
	const BString& fileName = image->fileName();
	if (fileName.size())
	{
		AutoChunk chunk(this, SIGN_FILENAME);
		stream->write(fileName);
		if (BReadWrite* rw = FindReadWrite(fileName))
		{
			BBuffer buffer;
			rw->write(buffer, image);
			stream->write(buffer.bytes());
		}
		return true;
	}
	else
	{
		{
			AutoChunk chunk(this, SIGN_FORMAT);
			int format = image->format();
			stream->write(format);
		}
		{
			AutoChunk chunk(this, SIGN_SIZE);
			BSize size = image->size();
			stream->write(size);
		}
		const BByteArray* pixels = image->pixels();
		if (pixels)
		{
			AutoChunk chunk(this, SIGN_PIXELS);
			int size = pixels->size();
			stream->write(size);
			stream->write(pixels->data(), size);
		}
	}
	return true;
}
bool member_BObcDocument::writePixmap(const BPixmap* pixmap)
{
	{
		AutoChunk chunk(this, SIGN_SIZE);
		BSize size = pixmap->size();
		stream->write(size);
	}
	return true;
}
bool member_BObcDocument::writeProgram(const BProgram* program)
{
	for (int i = 0; i < program->shaderCount(); i++)
	{
		const BShader* shader = program->shader(i);
		writeShader(shader);
	}
	for (int i = 0; i < program->uniformCount(); i++)
	{
		const BUniform* uniform = program->uniform(i);
		writeUniform(uniform);
	}
	return true;
}
bool member_BObcDocument::writeShader(const BShader* shader)
{
	{
		AutoChunk chunk(this, SIGN_TYPE);
		int type = shader->type();
		stream->write(type);
	}
	{
		AutoChunk chunk(this, SIGN_TEXT);
		const BString& text = shader->text();
		stream->write(text);
	}
	return true;
}
bool member_BObcDocument::writeUniform(const BUniform* uniform)
{
	{
		AutoChunk chunk(this, SIGN_SIGN);
		const BString& sign = uniform->sign();
		stream->write(sign);
	}
	{
		AutoChunk chunk(this, SIGN_TYPE);
		int type = uniform->type();
		stream->write(type);
	}
	{
		AutoChunk chunk(this, SIGN_SIZE);
		int size = uniform->size();
		stream->write(size);
	}
	return true;
}
bool member_BObcDocument::writePhysics(const BPhysics* physics)
{
	{
		AutoChunk chunk(this, SIGN_MASS);
		BReal mass = physics->mass();
		stream->write(mass);
	}
	{
		AutoChunk chunk(this, SIGN_FRICTION);
		BReal friction = physics->friction();
		stream->read(friction);
	}
	{
		AutoChunk chunk(this, SIGN_ELASTANE);
		BReal elastane = physics->elastane();
		stream->read(elastane);
	}
	{
		AutoChunk chunk(this, SIGN_FORCE);
		const BVector& force = physics->force();
		stream->read(force);
	}
	{
		AutoChunk chunk(this, SIGN_GRAVITY);
		const BVector& gravity = physics->gravity();
		stream->read(gravity);
	}
	return true;
}
bool member_BObcDocument::writeScript(const BScript* script)
{
	for (int i = 0; i < script->sourceCount(); i++)
	{
		const BSource* source = script->source(i);
		write(source);
	}
	{
		AutoChunk chunk(this, SIGN_SEQUENCE);
		const BExpHolderArray& sequence = script->sequence();
		int size = sequence.size();
		stream->write(size);
		for (int i = 0; i < sequence.size(); i++)
		{
			AutoChunk chunk(this, SIGN_EXP);
			writeExp(sequence[i]);
		}
	}
	return true;
}
bool member_BObcDocument::writeSource(const BSource* source)
{
	return true;
}
bool member_BObcDocument::writeExp(const BExp* exp)
{
	{
		AutoChunk chunk(this, SIGN_SYNTAX);
		stream->write(exp->syntax);
	}
	if (exp->info.size())
	{
		AutoChunk chunk(this, SIGN_INFORMATION);
		stream->write(exp->info);
	}
	if (exp->type.size())
	{
		AutoChunk chunk(this, SIGN_TYPE);
		stream->write(exp->type);
	}
	if (exp->name.size())
	{
		AutoChunk chunk(this, SIGN_NAME);
		stream->write(exp->name);
	}
	if (exp->value.valid())
	{
		AutoChunk chunk(this, SIGN_VALUE);
		if (exp->value.is<char>())
		{
			stream->write('c');
			stream->write((char)exp->value);
		}
		else if (exp->value.is<unsigned char>())
		{
			stream->write('b');
			stream->write((unsigned char)exp->value);
		}
		else if (exp->value.is<short>())
		{
			stream->write('s');
			stream->write((short)exp->value);
		}
		else if (exp->value.is<unsigned short>())
		{
			stream->write('t');
			stream->write((unsigned short)exp->value);
		}
		else if (exp->value.is<int>())
		{
			stream->write('i');
			stream->write((int)exp->value);
		}
		else if (exp->value.is<unsigned int>())
		{
			stream->write('u');
			stream->write((unsigned int)exp->value);
		}
		else if (exp->value.is<long long>())
		{
			stream->write('l');
			stream->write((long long)exp->value);
		}
		else if (exp->value.is<unsigned long long>())
		{
			stream->write('m');
			stream->write((unsigned long long)exp->value);
		}
		else if (exp->value.is<float>())
		{
			stream->write('f');
			stream->write((float)exp->value);
		}
		else if (exp->value.is<double>())
		{
			stream->write('d');
			stream->write((double)exp->value);
		}
		else if (exp->value.is<BString>())
		{
			stream->write('s');
			stream->write((const BString&)exp->value);
		}
	}
	if (int size = exp->params.size())
	{
		for (int i = 0; i < size; i++)
		{
			AutoChunk chunk(this, SIGN_EXP);
			writeExp(exp->params[i]);
		}
	}
	return true;
}
